package cn.com.headfree.deploy.controller;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.gta.edu.sdk.common.dto.ResultData;
import com.gta.edu.sdk.util.StringUtil;

import cn.com.headfree.deploy.vo.DockerVo;
import cn.com.headfree.deploy.vo.FileVo;

@CrossOrigin("*")
@RestController
@RequestMapping(value = "/deploy", produces = "application/json;charset=UTF-8")
public class DeployController {
	private static final Logger log = LogManager.getLogger(DeployController.class);
	@Value("${file.save.path}")
	private String filePath;
	@Value("${docker.login.cmd}")
	private String dockerLoginCmd;
	@Value("${docker.registry.url}")
	private String dockerRegistryUrl;
	private static final String CONFIG_FILE_NAME = "Dockerfile";

	@RequestMapping("/submitApp")
	public ResultData submitApp(@RequestParam("file") MultipartFile[] file, String imageName, String versionNo, String[] appName) {
		ResultData result = new ResultData();
		if (file == null || file != null && file.length == 0) {
			log.error("上传文件为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("上传文件为空，出现错误！");
			return result;
		}
		if (StringUtil.isNullOrEmpty(imageName) || StringUtil.isNullOrEmpty(versionNo)) {
			log.error("镜像名称或者版本号为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("镜像名称或者版本号为空，出现错误！");
			return result;
		}

		try {
			DockerVo vo = new DockerVo();
			vo.setImageName(imageName);
			vo.setVersionNo(versionNo);
			Set<String> fileNames = new HashSet<String>(file.length);
//			Set<String> appNames = new HashSet<String>(file.length);
			String fileName = null;
			File dest = null;
			for (int i = 0; i < file.length; i++) {
				fileName = file[i].getOriginalFilename();
				fileNames.add(fileName);
//				appNames.add(appName[i]);
				dest = new File(filePath, fileName);
				if (!dest.getParentFile().exists()) {
					dest.getParentFile().mkdirs();
				}
				if (dest.exists()) {
					dest.delete();
				}
				file[i].transferTo(dest);

			}
//			if (file.length != fileNames.size() || file.length != appNames.size()) {
//				log.error("上传的应用文件、应用名称为空，或者应用文件、应用名称相同，出现了错误！");
//				result.setSuccess(false);
//				result.setErrorMsg("上传的应用文件、应用名称为空，或者应用文件、应用名称相同，出现了错误！");
//				return result;
//			}
//			vo.setAppName(appNames);
			vo.setFileName(fileNames);
			result.setData(vo);
		} catch (Exception e) {
			log.error("上传文件失败，系统出现异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("上传文件失败，系统出现异常！");
		}
		return result;
	}

	@RequestMapping("/madeConfig")
	public ResultData madeConfig(@RequestBody DockerVo vo) {
		log.info("***********************开始执行创建镜像配置文件*****************************");
		ResultData result = new ResultData();
		InputStream is = null;
		BufferedReader br = null;
		BufferedWriter bw = null;
		FileOutputStream fos = null;
		try {
			is = DeployController.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
			InputStreamReader isr = new InputStreamReader(is,"UTF-8");
			String configFileName = CONFIG_FILE_NAME;
			File configFile = new File(filePath, configFileName);
			if (!configFile.exists()) {
				configFile.createNewFile();
			}
			br = new BufferedReader(isr);
			FileWriter fw = new FileWriter(configFile);
			bw = new BufferedWriter(fw);
			StringBuilder config = new StringBuilder();
			String lineStr = null;
//			String fileImageName = "${image-name}";
			String addAppFile = "${add-app-file}";
			String echoRunAppCommond = "${echo-run-app-commond}";
			StringBuilder echoRunAppCommondSB = new StringBuilder();
			StringBuilder echoRunAppCommondSBFileName = new StringBuilder();
			log.info("***********************开始写入配置文件*****************************");
			while ((lineStr = br.readLine()) != null) {
				// 修改镜像名称
//				if (lineStr.contains(fileImageName)) {
//					lineStr = lineStr.replace(fileImageName, vo.getImageName());
//				}
//				if (lineStr.contains(ArmsAgentFile)) {
//					String appPath = DeployController.class.getClassLoader().getResource("ArmsAgent.zip").getPath();
//					lineStr = lineStr.replace(ArmsAgentFile, appPath);
//				}
				if (lineStr.contains(echoRunAppCommond)) {
					echoRunAppCommondSB.append("RUN echo '");
					for (String appfileName : vo.getFileName()) {
						if (echoRunAppCommondSBFileName.length() > 0) {
//							echoRunAppCommondSBFileName.append(" & ${JAVA_HOME}/bin/java ${JVM_OPTS} ${CATALINA_OPTS} -jar ${ADMIN_HOME}/").append(appfileName);
							echoRunAppCommondSBFileName.append(" & ${JAVA_HOME}/bin/java ${JVM_OPTS} ${CATALINA_OPTS} -jar ${ADMIN_HOME}/").append(appfileName);
						} else {
//							echoRunAppCommondSBFileName.append("${JAVA_HOME}/bin/java ${JVM_OPTS} ${CATALINA_OPTS} -jar ${ADMIN_HOME}/").append(appfileName);
							echoRunAppCommondSBFileName.append("${JAVA_HOME}/bin/java ${JVM_OPTS} ${CATALINA_OPTS} -jar ${ADMIN_HOME}/").append(appfileName);
						}
					}
					echoRunAppCommondSB.append(echoRunAppCommondSBFileName).append("'> ${ADMIN_HOME}/start.sh && chmod +x ${ADMIN_HOME}/start.sh");
					lineStr = echoRunAppCommondSB.toString();
				}
				if (lineStr.contains(addAppFile)) {
					for (String appfileName : vo.getFileName()) {
						lineStr = "ADD " + appfileName + " ${ADMIN_HOME}/" + appfileName;
						bw.write(lineStr);
						bw.newLine();
						config.append(lineStr).append("<br/>");
					}
				} else {
					bw.write(lineStr);
					config.append(lineStr).append("<br/>");
					bw.newLine();
				}
			}
			bw.flush();
			log.info("***********************完成写入配置文件*****************************");
//			vo.setFileName(configFileName);
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("config", config);
			resultData.put("params", vo);
			result.setData(resultData);
		} catch (Exception e) {
			log.error("生成配置文件失败，系统出现异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("生成配置文件失败，系统出现异常！");
			return result;
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					log.error("关闭生成配置文件的输入流出现异常！", e);
				}
			}
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					log.error("关闭生成配置文件的输出流出现异常！", e);
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("关闭文件输入流出现异常！", e);
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					log.error("关闭写入armsAgent文件流出现异常！", e);
				}
			}
		}
//		try {
//			log.info("***********************开始写入armsAgent文件*****************************");
//			// 拷贝ArmsAgent.zip文件到部署目录中
//			is = DeployController.class.getClassLoader().getResourceAsStream(ARMS_AGENT_FILE);
//			File armsAgentFile = new File(filePath, ARMS_AGENT_FILE);
//			fos = new FileOutputStream(armsAgentFile);
//			if (!armsAgentFile.exists()) {
//				armsAgentFile.createNewFile();
//			}
//			byte[] buf = new byte[1024];
//			int index = -1;
//			while ((index = is.read(buf)) != -1) {
//				fos.write(buf,0,index);
//			}
//			log.info("***********************完成写入armsAgent文件*****************************");
//		} catch (Exception e) {
//			log.error("生成配置文件失败，系统出现异常！", e);
//			result.setSuccess(false);
//			result.setErrorMsg("生成配置文件失败，系统出现异常！");
//			return result;
//		} finally {
//			if (is != null) {
//				try {
//					is.close();
//				} catch (IOException e) {
//					log.error("关闭文件输入流出现异常！", e);
//				}
//			}
//			if (fos != null) {
//				try {
//					fos.close();
//				} catch (IOException e) {
//					log.error("关闭写入armsAgent文件流出现异常！", e);
//				}
//			}
//		}
		return result;
	}

	@RequestMapping("/madeImage")
	public ResultData madeImage(@RequestBody DockerVo vo) {
		ResultData result = new ResultData();
		try {
			StringBuilder cmdInfo = new StringBuilder();
			StringBuilder command = new StringBuilder("docker build -t ");
			StringBuilder image = new StringBuilder();
			image.append(dockerRegistryUrl).append(vo.getImageName()).append(":").append(vo.getVersionNo());
			command.append(image).append(" ./");
			log.info(command);
			cmdInfo.append(command).append("<br/>");

			String exeResult = this.execCommand(command.toString());
			// 判断执行结果
			boolean isSuccess = false;
			String[] lines = exeResult.toString().split("<br/>");
			for (String line : lines) {
				if (!StringUtil.isNullOrEmpty(line) && line.trim().contains("Successfully")) {
					isSuccess = true;
					break;
				}
			}

			// 删除掉上传的应用jar文件
			File dest = null;
			for (String fileName : vo.getFileName()) {
				dest = new File(filePath, fileName);
				if (dest.exists()) {
					dest.delete();
				}
			}

			log.info("exeResult:" + exeResult);
			cmdInfo.append(exeResult);
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("info", cmdInfo);
			resultData.put("imageName", image);
			resultData.put("result", isSuccess);
			result.setData(resultData);
		} catch (Exception e) {
			String errorInfo = "创建镜像文件，系统出现异常！";
			log.error(errorInfo, e);
			result.setSuccess(false);
			result.setErrorMsg(errorInfo);
		}
		return result;
	}

	@RequestMapping("/pushImageToStore")
	public ResultData pushImageToStore(String image) {
		ResultData result = new ResultData();
		try {
			StringBuilder cmdInfo = new StringBuilder();
			cmdInfo.append(this.dockerLoginCmd).append("<br/>");
			log.info(this.dockerLoginCmd);

			String exeResult = this.execCommand(this.dockerLoginCmd);
			cmdInfo.append(exeResult);
			log.info(exeResult);
			// 判断执行结果
			boolean isSuccess = false;
			String[] lines = exeResult.toString().split("<br/>");
			for (String line : lines) {
				if (!StringUtil.isNullOrEmpty(line) && line.trim().contains("Succeeded")) {
					isSuccess = true;
					break;
				}
			}
			if (isSuccess) {
				StringBuilder imageCmd = new StringBuilder("docker push ");
				imageCmd.append(image);
				cmdInfo.append(imageCmd).append("<br/>");
				log.info(imageCmd);
				String pushResult = this.execCommand(imageCmd.toString());
				cmdInfo.append(pushResult);
				log.info(pushResult);
				// 删除本地镜像
				Thread.sleep(30000);
				StringBuilder deleteImageCmd = new StringBuilder("docker rmi ");
				deleteImageCmd.append(image);
				cmdInfo.append(deleteImageCmd).append("<br/>");
				log.info(deleteImageCmd);
				String deleteImageResult = this.execCommand(deleteImageCmd.toString());
				cmdInfo.append(deleteImageResult);
			}
			
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("info", cmdInfo);
			resultData.put("imageName", image);
			resultData.put("result", isSuccess);
			result.setData(resultData);
		} catch (Exception e) {
			String errorInfo = "推送镜像，系统出现异常！";
			log.error(errorInfo, e);
			result.setSuccess(false);
			result.setErrorMsg(errorInfo);
		}
		return result;
	}

	@RequestMapping("/upload")
	public ResultData upload(@RequestParam("file") MultipartFile file, FileVo vo) {
		ResultData result = new ResultData();
		if (file.isEmpty()) {
			log.error("上传文件为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("上传文件为空，出现错误！");
			return result;
		}
		if (StringUtil.isNullOrEmpty(vo.getImageName()) || StringUtil.isNullOrEmpty(vo.getVersionNo())) {
			log.error("镜像名称或者版本号为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("镜像名称或者版本号为空，出现错误！");
			return result;
		}
		try {
			String fileName = file.getOriginalFilename();
			File dest = new File(filePath, fileName);
			if (!dest.getParentFile().exists()) {
				dest.getParentFile().mkdirs();
			}
			if (dest.exists()) {
				dest.delete();
			}
			file.transferTo(dest);
			vo.setFileName(fileName);
			result.setData(vo);
		} catch (Exception e) {
			log.error("上传文件失败，系统出现异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("上传文件失败，系统出现异常！");
		}
		return result;
	}

	@RequestMapping("/config")
	public ResultData config(FileVo vo) {
		ResultData result = new ResultData();
		InputStream is = null;
		String fileName = "${file_name}";
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			is = DeployController.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
			InputStreamReader isr = new InputStreamReader(is);
			String configFileName = CONFIG_FILE_NAME;
			File configFile = new File(filePath, configFileName);
			if (!configFile.exists()) {
				configFile.createNewFile();
			}
			br = new BufferedReader(isr);
			FileWriter fw = new FileWriter(configFile);
			bw = new BufferedWriter(fw);
			StringBuilder config = new StringBuilder();
			String lineStr = null;
			while ((lineStr = br.readLine()) != null) {
				if (lineStr.contains(fileName)) {
					lineStr = lineStr.replace(fileName, vo.getFileName());
				}
				bw.write(lineStr);
				config.append(lineStr).append("<br/>");
				bw.newLine();
			}
			bw.flush();
//			vo.setFileName(configFileName);
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("config", config);
			resultData.put("params", vo);
			result.setData(resultData);
		} catch (Exception e) {
			log.error("生成配置文件失败，系统出现异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("生成配置文件失败，系统出现异常！");
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					log.error("关闭生成配置文件的输入流出现异常！", e);
				}
			}
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					log.error("关闭生成配置文件的输出流出现异常！", e);
				}
			}
		}
		return result;
	}

	@RequestMapping("/createImage")
	public ResultData createImage(FileVo vo) {
		ResultData result = new ResultData();
		try {
			StringBuilder cmdInfo = new StringBuilder();
			StringBuilder command = new StringBuilder("docker build -t ");
			StringBuilder image = new StringBuilder();
			image.append(dockerRegistryUrl).append(vo.getImageName()).append(":").append(vo.getVersionNo());
			command.append(image).append(" ./");
			log.info(command);
			cmdInfo.append(command).append("<br/>");

			String exeResult = this.execCommand(command.toString());
//			// 模拟返回结果数据
//			StringBuilder exeResult = new StringBuilder();
//			exeResult.append("Step 1/10 : FROM cr.registry.ah-1.res.sgmc.sgcc.com.cn/ixt-common/edas:latest").append("<br/>");
//			exeResult.append(" ---> 7c9cb73228fb").append("<br/>");
//			exeResult.append("Step 2/10 : ENV APP_HOME /home/admin").append("<br/>");
//			exeResult.append(" ---> Using cache").append("<br/>");
//			exeResult.append(" ---> ae1868051b52").append("<br/>");
//			exeResult.append("Step 3/10 : ENV JAR_FILE comm-front-frame-0.0.1.jar").append("<br/>");
//			exeResult.append(" ---> Using cache").append("<br/>");
//			exeResult.append(" ---> 180b2fad350f").append("<br/>");
//			exeResult.append("Step 4/10 : RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime").append("<br/>");
//			exeResult.append(" ---> Using cache").append("<br/>");
//			exeResult.append(" ---> f070fc1a220d").append("<br/>");
//			exeResult.append("Step 5/10 : RUN echo 'Asia/Shanghai' >/etc/timezone").append("<br/>");
//			exeResult.append(" ---> Using cache").append("<br/>");
//			exeResult.append(" ---> 95040ca4772c").append("<br/>");
//			exeResult.append("Step 6/10 : ENV LANG=\"en_US.UTF-8\"").append("<br/>");
//			exeResult.append(" ---> Using cache").append("<br/>");
//			exeResult.append(" ---> 6c212d46be80").append("<br/>");
//			exeResult.append("Step 7/10 : ADD ${JAR_FILE} ${APP_HOME}/").append("<br/>");
//			exeResult.append(" ---> d7fbea49f649").append("<br/>");
//			exeResult.append("Step 8/10 : RUN echo 'java -jar ${CATALINA_OPTS} ${APP_HOME}/${JAR_FILE}'> ${APP_HOME}/start.sh && chmod +x ${APP_HOME}/start.sh").append("<br/>");
//			exeResult.append(" ---> Running in 055fff71929c").append("<br/>");
//			exeResult.append("Removing intermediate container 055fff71929c").append("<br/>");
//			exeResult.append(" ---> a9b1d6220b2c").append("<br/>");
//			exeResult.append("Step 9/10 : WORKDIR ${APP_HOME}").append("<br/>");
//			exeResult.append(" ---> Running in 50c56627edd3").append("<br/>");
//			exeResult.append("Removing intermediate container 50c56627edd3").append("<br/>");
//			exeResult.append(" ---> 6f30ad801eb8").append("<br/>");
//			exeResult.append("Step 10/10 : CMD [\"/bin/bash\", \"/home/admin/start.sh\"]").append("<br/>");
//			exeResult.append(" ---> Running in 49f4477ae4c8").append("<br/>");
//			exeResult.append("Removing intermediate container 49f4477ae4c8").append("<br/>");
//			exeResult.append(" ---> 86c88dda7785").append("<br/>");
//			exeResult.append("Successfully built 86c88dda7785").append("<br/>");
//			exeResult.append("Successfully tagged cr.registry.ah-1.res.sgmc.sgcc.com.cn/ixt-common/comm-front-frame:0.2.5").append("<br/>");

			// 判断执行结果
			boolean isSuccess = false;
			String[] lines = exeResult.toString().split("<br/>");
			for (String line : lines) {
				if (!StringUtil.isNullOrEmpty(line) && line.trim().contains("Successfully")) {
					isSuccess = true;
					break;
				}
			}

			// 删除掉上传的应用jar文件
			File dest = new File(filePath, vo.getFileName());
			if (dest.exists()) {
				dest.delete();
			}

			log.info("exeResult:" + exeResult);
			cmdInfo.append(exeResult);
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("info", cmdInfo);
			resultData.put("imageName", image);
			resultData.put("result", isSuccess);
			result.setData(resultData);
		} catch (Exception e) {
			String errorInfo = "创建镜像文件，系统出现异常！";
			log.error(errorInfo, e);
			result.setSuccess(false);
			result.setErrorMsg(errorInfo);
		}
		return result;
	}

	private String execCommand(String cmd) throws Exception {
		StringBuilder result = new StringBuilder();
		Runtime rt = Runtime.getRuntime();
		Process proc = rt.exec(cmd);
		InputStream stderr = proc.getInputStream();
		InputStreamReader isr = new InputStreamReader(stderr, "GBK");
		BufferedReader br = new BufferedReader(isr);
		String line = null;
		while ((line = br.readLine()) != null) {
			result.append(line).append("<br/>");
		}
		return result.toString();
	}

	@RequestMapping("/pushImage")
	public ResultData pushImage(String image) {
		ResultData result = new ResultData();
		try {
			StringBuilder cmdInfo = new StringBuilder();
			cmdInfo.append(this.dockerLoginCmd).append("<br/>");
			log.info(this.dockerLoginCmd);

//			// 模拟登陆镜像仓库
//			StringBuilder exeResult = new StringBuilder();
//			exeResult.append("WARNING! Using --password via the CLI is insecure. Use --password-stdin.").append("<br/>");
//			exeResult.append("WARNING! Your password will be stored unencrypted in /root/.docker/config.json.").append("<br/>");
//			exeResult.append("Configure a credential helper to remove this warning. See").append("<br/>");
//			exeResult.append("https://docs.docker.com/engine/reference/commandline/login/#credentials-store").append("<br/>").append("<br/>");
//			exeResult.append("Login Succeeded").append("<br/>");

			String exeResult = this.execCommand(this.dockerLoginCmd);

			// 判断执行结果
			boolean isSuccess = false;
			String[] lines = exeResult.toString().split("<br/>");
			for (String line : lines) {
				if (!StringUtil.isNullOrEmpty(line) && line.trim().contains("Succeeded")) {
					isSuccess = true;
					break;
				}
			}
			cmdInfo.append(exeResult);
			log.info(exeResult);
			StringBuilder imageCmd = new StringBuilder("docker push ");
			imageCmd.append(image);
			cmdInfo.append(imageCmd).append("<br/>");
			log.info(imageCmd);

//			//模拟推镜像到镜像仓库
//			StringBuilder pushResult = new StringBuilder();
//			pushResult.append("The push refers to repository [cr.registry.ah-1.res.sgmc.sgcc.com.cn/ixt-common/comm-quick-deploy-server]").append("<br/>");
//			pushResult.append("713560bd1d6c: Pushed ").append("<br/>");
//			pushResult.append("e024c8df0442: Pushed ").append("<br/>");
//			pushResult.append("f2c9d56f4296: Layer already exists ").append("<br/>");
//			pushResult.append("92d00de04fb8: Layer already exists").append("<br/>");
//			pushResult.append("196ce365562f: Layer already exists").append("<br/>");
//			pushResult.append("17e94c4cd6bb: Layer already exists").append("<br/>");
//			pushResult.append("3785c7a3e26f: Layer already exists").append("<br/>");
//			pushResult.append("edf3aa290fb3: Layer already exists").append("<br/>");
//			pushResult.append("1.1.3: digest: sha256:30ebbe1fe07f442496fbfa74ea1eb581ab0cd34bafbf3c0c610516a779f03dda size: 1993");

			String pushResult = this.execCommand(imageCmd.toString());
			cmdInfo.append(pushResult);
			Map<String, Object> resultData = new HashMap<String, Object>();
			resultData.put("info", cmdInfo);
			resultData.put("imageName", image);
			resultData.put("result", isSuccess);
			result.setData(resultData);
			log.info(pushResult);
		} catch (Exception e) {
			String errorInfo = "推送镜像，系统出现异常！";
			log.error(errorInfo, e);
			result.setSuccess(false);
			result.setErrorMsg(errorInfo);
		}
		return result;
	}
}
